home *** CD-ROM | disk | FTP | other *** search
Wrap
LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) NNNNAAAAMMMMEEEE libexpect - programmed dialogue with interactive programs - C functions DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN This library contains functions that allow Expect to be used as a Tcl extension or to be used directly from C or C++ (without Tcl). Adding Expect as a Tcl extension is very short and simple, so that will be covered first. SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS ####iiiinnnncccclllluuuuddddeeee eeeexxxxppppeeeecccctttt____ttttccccllll....hhhh EEEExxxxpppp____IIIInnnniiiitttt((((iiiinnnntttteeeerrrrpppp))));;;; cccccccc ffffiiiilllleeeessss............ ----lllleeeexxxxppppeeeecccctttt ----llllttttccccllll ----llllmmmm The Exp_Init function adds expect commands to the named interpreter. It avoids overwriting commands that already exist, however aliases beginning with "exp_" are always created for expect commands. So for example, "send" can be used as "exp_send". Generally, you should only call Expect commands via Tcl_Eval. Certain auxiliary functions may be called directly. They are summarized below. They may be useful in constructing your own main. Look at the file exp_main_exp.c in the Expect distribution as a prototype main. Another prototype is tclAppInit.c in the Tcl source distribution. A prototype for working with Tk is in exp_main_tk.c in the Expect distribution. int exp_cmdlinecmds; int exp_interactive; FILE *exp_cmdfile; char *exp_cmdfilename; int exp_tcl_debugger_available; void exp_parse_argv(Tcl_Interp *,int argc,char **argv); int exp_interpreter(Tcl_Interp *); void exp_interpret_cmdfile(Tcl_Interp *,FILE *); void exp_interpret_cmdfilename(Tcl_Interp *,char *); void exp_interpret_rcfiles(Tcl_Interp *,int my_rc,int sys_rc); char * exp_cook(char *s,int *len); void (*exp_app_exit)EXP_PROTO((Tcl_Interp *); void exp_exit(Tcl_Interp *,int status); void exp_exit_handlers(Tcl_Interp *); void exp_error(Tcl_Interp,char *,...); eeeexxxxpppp____ccccmmmmddddlllliiiinnnneeeeccccmmmmddddssss is 1 if Expect has been invoked with commands on the program command-line (using "-c" for example). eeeexxxxpppp____iiiinnnntttteeeerrrraaaaccccttttiiiivvvveeee is 1 if Expect has been invoked with the -i flag or if no commands or script is being Page 1 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) invoked. eeeexxxxpppp____ccccmmmmddddffffiiiilllleeee is a stream from which Expect will read commands. eeeexxxxpppp____ccccmmmmddddffffiiiilllleeeennnnaaaammmmeeee is the name of a file which Expect will open and read commands from. eeeexxxxpppp____ttttccccllll____ddddeeeebbbbuuuuggggggggeeeerrrr____aaaavvvvaaaaiiiillllaaaabbbblllleeee is 1 if the debugger has been armed. eeeexxxxpppp____ppppaaaarrrrsssseeee____aaaarrrrggggvvvv reads the representation of the command line. Based on what is found, any of the other variables listed here are initialized appropriately. eeeexxxxpppp____iiiinnnntttteeeerrrrpppprrrreeeetttteeeerrrr interactively prompts the user for commands and evaluates them. eeeexxxxpppp____iiiinnnntttteeeerrrrpppprrrreeeetttt____ccccmmmmddddffffiiiilllleeee reads the given stream and evaluates any commands found. eeeexxxxpppp____iiiinnnntttteeeerrrrpppprrrreeeetttt____ccccmmmmddddffffiiiilllleeeennnnaaaammmmeeee opens the named file and evaluates any commands found. eeeexxxxpppp____iiiinnnntttteeeerrrrpppprrrreeeetttt____rrrrccccffffiiiilllleeeessss reads and evalutes the .rc files. If my_rc is zero, then ~/.expectrc is skipped. If sys_rc is zero, then the system-wide expectrc file is skipped. eeeexxxxpppp____ccccooooooookkkk returns a static buffer containing the argument reproduced with newlines replaced by carriage-return linefeed sequences. The primary purpose of this is to allow messages to be produced without worrying about whether the terminal is in raw mode or cooked mode. If length is zero, it is computed via strlen. eeeexxxxpppp____eeeerrrrrrrroooorrrr iiiissss aaaa pppprrrriiiinnnnttttffff----lllliiiikkkkeeee ffffuuuunnnnccccttttiiiioooonnnn tttthhhhaaaatttt to interp->result. SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS ####iiiinnnncccclllluuuuddddeeee <<<<eeeexxxxppppeeeecccctttt....hhhh>>>> iiiinnnntttt eeeexxxxpppp____ssssppppaaaawwwwnnnnllll((((ffffiiiilllleeee,,,, aaaarrrrgggg0000 [[[[,,,, aaaarrrrgggg1111,,,, ............,,,, aaaarrrrggggnnnn]]]] ((((cccchhhhaaaarrrr ****))))0000))));;;; cccchhhhaaaarrrr ****ffffiiiilllleeee;;;; cccchhhhaaaarrrr ****aaaarrrrgggg0000,,,, ****aaaarrrrgggg1111,,,, ............ ****aaaarrrrggggnnnn;;;; iiiinnnntttt eeeexxxxpppp____ssssppppaaaawwwwnnnnvvvv((((ffffiiiilllleeee,,,,aaaarrrrggggvvvv))));;;; cccchhhhaaaarrrr ****ffffiiiilllleeee,,,, ****aaaarrrrggggvvvv[[[[ ]]]];;;; FFFFIIIILLLLEEEE **** eeeexxxxpppp____ppppooooppppeeeennnn((((ccccoooommmmmmmmaaaannnndddd))));;;; cccchhhhaaaarrrr ****ccccoooommmmmmmmaaaannnndddd;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____ppppiiiidddd;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____ttttttttyyyyiiiinnnniiiitttt;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____ttttttttyyyyccccooooppppyyyy;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____ccccoooonnnnssssoooolllleeee;;;; eeeexxxxtttteeeerrrrnnnn cccchhhhaaaarrrr ****eeeexxxxpppp____ssssttttttttyyyy____iiiinnnniiiitttt;;;; eeeexxxxtttteeeerrrrnnnn vvvvooooiiiidddd ((((****eeeexxxxpppp____cccclllloooosssseeee____iiiinnnn____cccchhhhiiiilllldddd))))(((())));;;; eeeexxxxtttteeeerrrrnnnn vvvvooooiiiidddd ((((****eeeexxxxpppp____cccchhhhiiiilllldddd____eeeexxxxeeeecccc____pppprrrreeeelllluuuuddddeeee))))(((())));;;; eeeexxxxtttteeeerrrrnnnn vvvvooooiiiidddd eeeexxxxpppp____cccclllloooosssseeee____ttttccccllll____ffffiiiilllleeeessss(((())));;;; cccccccc ffffiiiilllleeeessss............ ----lllleeeexxxxppppeeeecccctttt ----llllttttccccllll ----llllmmmm Page 2 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN eeeexxxxpppp____ssssppppaaaawwwwnnnnllll and eeeexxxxpppp____ssssppppaaaawwwwnnnnvvvv fork a new process so that its stdin, stdout, and stderr can be written and read by the current process. _f_i_l_e is the name of a file to be executed. The _a_r_g pointers are null-terminated strings. Following the style of execve(), _a_r_g_0 (or _a_r_g_v[_0]) is customarily a duplicate of the name of the file. Three interfaces are available, eeeexxxxpppp____ssssppppaaaawwwwnnnnllll is useful when the number of arguments is known at compile time. eeeexxxxpppp____ssssppppaaaawwwwnnnnvvvv is useful when the number of arguments is not known at compile time. eeeexxxxpppp____ppppooooppppeeeennnn is explained later on. If the process is successfully created, a file descriptor is returned which corresponds to the process's stdin, stdout and stderr. A stream may be associated with the file descriptor by using fdopen(). (This should almost certainly be followed by setbuf() to unbuffer the I/O.) Closing the file descriptor will typically be detected by the process as an EOF. Once such a process exits, it should be waited upon (via wait) in order to free up the kernel process slot. (Some systems allow you to avoid this if you ignore the SIGCHLD signal). eeeexxxxpppp____ppppooooppppeeeennnn is yet another interface, styled after popen(). It takes a Bourne shell command line, and returns a stream that corresponds to the process's stdin, stdout and stderr. The actual implementation of eeeexxxxpppp____ppppooooppppeeeennnn below demonstrates eeeexxxxpppp____ssssppppaaaawwwwnnnnllll. FILE * exp_popen(program) char *program; { FILE *fp; int ec; if (0 > (ec = exp_spawnl("sh","sh","-c",program,(char *)0))) return(0); if (NULL == (fp = fdopen(ec,"r+")) return(0); setbuf(fp,(char *)0); return(fp); } After a process is started, the variable eeeexxxxpppp____ppppiiiidddd is set to the process-id of the new process. The variable eeeexxxxpppp____ppppttttyyyy____ssssllllaaaavvvveeee____nnnnaaaammmmeeee is set to the name of the slave side of the pty. The spawn functions uses a pty to communicate with the process. By default, the pty is initialized the same way as Page 3 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) the user's tty (if possible, i.e., if the environment has a controlling terminal.) This initialization can be skipped by setting exp_ttycopy to 0. The pty is further initialized to some system wide defaults if exp_ttyinit is non-zero. The default is generally comparable to "stty sane". The tty setting can be further modified by setting the variable eeeexxxxpppp____ssssttttttttyyyy____iiiinnnniiiitttt. This variable is interpreted in the style of stty arguments. For example, exp_stty_init = "sane"; repeats the default initialization. On some systems, it is possible to redirect console output to ptys. If this is supported, you can force the next spawn to obtain the console output by setting the variable eeeexxxxpppp____ccccoooonnnnssssoooolllleeee to 1. Between the time a process is started and the new program is given control, the spawn functions can clean up the environment by closing file descriptors. By default, the only file descriptors closed ones internal to Expect and any marked "close-on-exec". If needed, you can close additional file descriptors by creating an appropriate function and assigning it to exp_close_in_child. The function will be called after the fork and before the exec. (This also modifies the behavior of the spawn command in Expect.) If you are also using Tcl, it may be convenient to use the function exp_close_tcl_files which closes all files between the default standard file descriptors and the highest descriptor known to Tcl. (Expect does this.) The function exp_child_exec_prelude is the last function called prior to the actual exec in the child. You can redefine this for effects such as manipulating the uid or the signals. IIIIFFFF YYYYOOOOUUUU WWWWAAAANNNNTTTT TTTTOOOO AAAALLLLLLLLOOOOCCCCAAAATTTTEEEE YYYYOOOOUUUURRRR OOOOWWWWNNNN PPPPTTTTYYYY eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____aaaauuuuttttooooaaaallllllllooooccccppppttttyyyy;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____ppppttttyyyy[[[[2222]]]];;;; The spawn functions use a pty to communicate with the process. By default, a pty is automatically allocated each time a process is spawned. If you want to allocate ptys yourself, before calling one of the spawn functions, set eeeexxxxpppp____aaaauuuuttttooooaaaallllllllooooccccppppttttyyyy to 0, eeeexxxxpppp____ppppttttyyyy[[[[0000]]]] to the master pty file descriptor and eeeexxxxpppp____ppppttttyyyy[[[[1111]]]] to the slave pty file descriptor. The expect library will not do any pty initializations Page 4 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) (e.g., exp_stty_init will not be used). The slave pty file descriptor will be automatically closed when the process is spawned. After the process is started, all further communication takes place with the master pty file descriptor. eeeexxxxpppp____ssssppppaaaawwwwnnnnllll and eeeexxxxpppp____ssssppppaaaawwwwnnnnvvvv duplicate the shell's actions in searching for an executable file in a list of directories. The directory list is obtained from the environment. EEEEXXXXPPPPEEEECCCCTTTT PPPPRRRROOOOCCCCEEEESSSSSSSSIIIINNNNGGGG While it is possible to use read() to read information from a process spawned by eeeexxxxpppp____ssssppppaaaawwwwnnnnllll or eeeexxxxpppp____ssssppppaaaawwwwnnnnvvvv, more convenient functions are provided. They are as follows: iiiinnnntttt eeeexxxxpppp____eeeexxxxppppeeeeccccttttllll((((ffffdddd,,,,ttttyyyyppppeeee1111,,,,ppppaaaatttttttteeeerrrrnnnn1111,,,,[[[[rrrreeee1111,,,,]]]],,,,vvvvaaaalllluuuueeee1111,,,,ttttyyyyppppeeee2222,,,,............,,,,eeeexxxxpppp____eeeennnndddd))));;;; iiiinnnntttt ffffdddd;;;; eeeennnnuuuummmm eeeexxxxpppp____ttttyyyyppppeeee ttttyyyyppppeeee;;;; cccchhhhaaaarrrr ****ppppaaaatttttttteeeerrrrnnnn1111,,,, ****ppppaaaatttttttteeeerrrrnnnn2222,,,, ............;;;; rrrreeeeggggeeeexxxxpppp ****rrrreeee1111,,,, ****rrrreeee2222,,,, ............;;;; iiiinnnntttt vvvvaaaalllluuuueeee1111,,,, vvvvaaaalllluuuueeee2222,,,, ............;;;; iiiinnnntttt eeeexxxxpppp____ffffeeeexxxxppppeeeeccccttttllll((((ffffpppp,,,,ttttyyyyppppeeee1111,,,,ppppaaaatttttttteeeerrrrnnnn1111,,,,[[[[rrrreeee1111,,,,]]]]vvvvaaaalllluuuueeee1111,,,,ttttyyyyppppeeee2222,,,,............,,,,eeeexxxxpppp____eeeennnndddd))));;;; FFFFIIIILLLLEEEE ****ffffpppp;;;; eeeennnnuuuummmm eeeexxxxpppp____ttttyyyyppppeeee ttttyyyyppppeeee;;;; cccchhhhaaaarrrr ****ppppaaaatttttttteeeerrrrnnnn1111,,,, ****ppppaaaatttttttteeeerrrrnnnn2222,,,, ............;;;; rrrreeeeggggeeeexxxxpppp ****rrrreeee1111,,,, ****rrrreeee2222,,,, ............;;;; iiiinnnntttt vvvvaaaalllluuuueeee1111,,,, vvvvaaaalllluuuueeee2222,,,, ............;;;; eeeennnnuuuummmm eeeexxxxpppp____ttttyyyyppppeeee {{{{ eeeexxxxpppp____eeeennnndddd,,,, eeeexxxxpppp____gggglllloooobbbb,,,, eeeexxxxpppp____eeeexxxxaaaacccctttt,,,, eeeexxxxpppp____rrrreeeeggggeeeexxxxpppp,,,, eeeexxxxpppp____ccccoooommmmppppiiiilllleeeedddd,,,, eeeexxxxpppp____nnnnuuuullllllll,,,, }}}};;;; ssssttttrrrruuuucccctttt eeeexxxxpppp____ccccaaaasssseeee {{{{ cccchhhhaaaarrrr ****ppppaaaatttttttteeeerrrrnnnn;;;; rrrreeeeggggeeeexxxxpppp ****rrrreeee;;;; eeeennnnuuuummmm eeeexxxxpppp____ttttyyyyppppeeee ttttyyyyppppeeee;;;; iiiinnnntttt vvvvaaaalllluuuueeee;;;; }}}};;;; iiiinnnntttt eeeexxxxpppp____eeeexxxxppppeeeeccccttttvvvv((((ffffdddd,,,,ccccaaaasssseeeessss))));;;; iiiinnnntttt ffffdddd;;;; ssssttttrrrruuuucccctttt eeeexxxxpppp____ccccaaaasssseeee ****ccccaaaasssseeeessss;;;; Page 5 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) iiiinnnntttt eeeexxxxpppp____ffffeeeexxxxppppeeeeccccttttvvvv((((ffffpppp,,,,ccccaaaasssseeeessss))));;;; FFFFIIIILLLLEEEE ****ffffpppp;;;; ssssttttrrrruuuucccctttt eeeexxxxpppp____ccccaaaasssseeee ****ccccaaaasssseeeessss;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____ttttiiiimmmmeeeeoooouuuutttt;;;; eeeexxxxtttteeeerrrrnnnn cccchhhhaaaarrrr ****eeeexxxxpppp____mmmmaaaattttcccchhhh;;;; eeeexxxxtttteeeerrrrnnnn cccchhhhaaaarrrr ****eeeexxxxpppp____mmmmaaaattttcccchhhh____eeeennnndddd;;;; eeeexxxxtttteeeerrrrnnnn cccchhhhaaaarrrr ****eeeexxxxpppp____bbbbuuuuffffffffeeeerrrr;;;; eeeexxxxtttteeeerrrrnnnn cccchhhhaaaarrrr ****eeeexxxxpppp____bbbbuuuuffffffffeeeerrrr____eeeennnndddd;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____mmmmaaaattttcccchhhh____mmmmaaaaxxxx;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____ffffuuuullllllll____bbbbuuuuffffffffeeeerrrr;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____rrrreeeemmmmoooovvvveeee____nnnnuuuullllllllssss;;;; The functions wait until the output from a process matches one of the patterns, a specified time period has passed, or an EOF is seen. The first argument to each function is either a file descriptor or a stream. Successive sets of arguments describe patterns and associated integer values to return when the pattern matches. The type argument is one of four values. exp_end indicates that no more patterns appear. exp_glob indicates that the pattern is a glob-style string pattern. exp_exact indicates that the pattern is an exact string. exp_regexp indicates that the pattern is a regexp-style string pattern. exp_compiled indicates that the pattern is a regexp-style string pattern, and that its compiled form is also provided. exp_null indicates that the pattern is a null (for debugging purposes, a string pattern must also follow - for debugging purposes). If the compiled form is not provided with the functions eeeexxxxpppp____eeeexxxxppppeeeeccccttttllll and eeeexxxxpppp____ffffeeeexxxxppppeeeeccccttttllll, , any pattern compilation done internally is thrown away after the function returns. The functions eeeexxxxpppp____eeeexxxxppppeeeeccccttttvvvv and eeeexxxxpppp____ffffeeeexxxxppppeeeeccccttttvvvv will automatically compile patterns and will not throw them away. Instead, they must be discarded by the user, by calling free on each pattern. It is only necessary to discard them, the last time the cases are used. Regexp subpatterns matched are stored in the compiled regexp. Assuming "re" contains a compiled regexp, the matched string can be found in re->startp[0]. The match substrings (according to the parentheses) in the original pattern can be found in re->startp[1], re->startp[2], and so on, up to re->startp[9]. The corresponding strings ends are re->endp[x] where x is that same index as for the string start. Page 6 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) The type exp_null matches if a null appears in the input. The variable exp_remove_nulls must be set to 0 to prevent nulls from being automatically stripped. By default, exp_remove_nulls is set to 1 and nulls are automatically stripped. eeeexxxxpppp____eeeexxxxppppeeeeccccttttvvvv and eeeexxxxpppp____ffffeeeexxxxppppeeeeccccttttvvvv are useful when the number of patterns is not known in advance. In this case, the sets are provided in an array. The end of the array is denoted by a struct exp_case with type exp_end. For the rest of this discussion, these functions will be referred to generically as _e_x_p_e_c_t. If a pattern matches, then the corresponding integer value is returned. Values need not be unique, however they should be positive to avoid being mistaken for EXP_EOF, EXP_TIMEOUT, or EXP_FULLBUFFER. Upon EOF or timeout, the value EEEEXXXXPPPP____EEEEOOOOFFFF or EEEEXXXXPPPP____TTTTIIIIMMMMEEEEOOOOUUUUTTTT is returned. The default timeout period is 10 seconds but may be changed by setting the variable eeeexxxxpppp____ttttiiiimmmmeeeeoooouuuutttt. A value of -1 disables a timeout from occurring. A value of 0 causes the expect function to return immediately (i.e., poll) after one read(). However it must be preceded by a function such as select, poll, or an event manager callback to guarantee that there is data to be read. If the variable exp_full_buffer is 1, then EXP_FULLBUFFER is returned if exp_buffer fills with no pattern having matched. When the expect function returns, eeeexxxxpppp____bbbbuuuuffffffffeeeerrrr points to the buffer of characters that was being considered for matching. eeeexxxxpppp____bbbbuuuuffffffffeeeerrrr____eeeennnndddd ppppooooiiiinnnnttttssss ttttoooo oooonnnneeee ppppaaaasssstttt tttthhhheeee If a match occurred, eeeexxxxpppp____mmmmaaaattttcccchhhh points into eeeexxxxpppp____bbbbuuuuffffffffeeeerrrr where the match began. eeeexxxxpppp____mmmmaaaattttcccchhhh____eeeennnndddd points to one character past where the match ended. Each time new input arrives, it is compared to each pattern in the order they are listed. Thus, you may test for absence of a match by making the last pattern something guaranteed to appear, such as a prompt. In situations where there is no prompt, you must check for EEEEXXXXPPPP____TTTTIIIIMMMMEEEEOOOOUUUUTTTT (just like you would if you were interacting manually). More philosophy and strategies on specifying eeeexxxxppppeeeecccctttt patterns can be found in the documentation on the eeeexxxxppppeeeecccctttt program, itself. See SEE ALSO below. Patterns are the usual C-shell-style regular expressions. For example, the following fragment looks for a successful login, such as from a telnet dialogue. switch (exp_expectl( exp_glob,"connected",CONN, Page 7 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) exp_glob,"busy",BUSY, exp_glob,"failed",ABORT, exp_glob,"invalid password",ABORT, exp_end)) { case CONN: /* logged in successfully */ break; case BUSY: /* couldn't log in at the moment */ break; case EXP_TIMEOUT: case ABORT: /* can't log in at any moment! */ break; default: /* problem with expect */ } Asterisks (as in the example above) are a useful shorthand for omitting line-termination characters and other detail. Patterns must match the entire output of the current process (since the previous read on the descriptor or stream). More than 2000 bytes of output can force earlier bytes to be "forgotten". This may be changed by setting the variable eeeexxxxpppp____mmmmaaaattttcccchhhh____mmmmaaaaxxxx. Note that excessively large values can slow down the pattern matcher. RRRRUUUUNNNNNNNNIIIINNNNGGGG IIIINNNN TTTTHHHHEEEE BBBBAAAACCCCKKKKGGGGRRRROOOOUUUUNNNNDDDD eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____ddddiiiissssccccoooonnnnnnnneeeecccctttteeeedddd;;;; iiiinnnntttt eeeexxxxpppp____ddddiiiissssccccoooonnnnnnnneeeecccctttt(((())));;;; It is possible to move a process into the background after it has begun running. A typical use for this is to read passwords and then go into the background to sleep before using the passwords to do real work. To move a process into the background, fork, call exp_disconnect() in the child process and exit() in the parent process. This disassociates your process from the controlling terminal. If you wish to move a process into the background in a different way, you must set the variable exp_disconnected to 1. This allows processes spawned after this point to be started correctly. MMMMUUUULLLLTTTTIIIIPPPPLLLLEEEEXXXXIIIINNNNGGGG By default, the expect functions block inside of a read on a single file descriptor. If you want to wait on patterns from multiple file descriptors, use select, poll, or an event manager. They will tell you what file descriptor is ready to read. When a file descriptor is ready to read, you can use the expect functions to do one and only read by setting timeout to 0. SSSSLLLLAAAAVVVVEEEE CCCCOOOONNNNTTTTRRRROOOOLLLL PPPPaaaaggggeeee 8888 ((((pppprrrriiiinnnntttteeeedddd 7777////22223333////99995555)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) vvvvooooiiiidddd eeeexxxxpppp____ssssllllaaaavvvveeee____ccccoooonnnnttttrrrroooollll((((ffffdddd,,,,eeeennnnaaaabbbblllleeee)))) iiiinnnntttt ffffdddd;;;; iiiinnnntttt eeeennnnaaaabbbblllleeee;;;; Pty trapping is normally done automatically by the expect functions. However, if you want to issue an ioctl, for example, directly on the slave device, you should temporary disable trapping. Pty trapping can be controlled with exp_slave_control. The first argument is the file descriptor corresponding to the spawned process. The second argument is a 0 if trapping is to be disabled and 1 if it is to be enabled. EEEERRRRRRRROOOORRRRSSSS All functions indicate errors by returning -1 and setting errno. Errors that occur after the spawn functions fork (e.g., attempting to spawn a non-existent program) are written to the process's stderr, and will be read by the first eeeexxxxppppeeeecccctttt. SSSSIIIIGGGGNNNNAAAALLLLSSSS eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____rrrreeeeaaaaddddiiiinnnngggg;;;; eeeexxxxtttteeeerrrrnnnn jjjjmmmmpppp____bbbbuuuuffff eeeexxxxpppp____rrrreeeeaaaaddddeeeennnnvvvv;;;; eeeexxxxppppeeeecccctttt uses alarm() to timeout, thus if you generate alarms during eeeexxxxppppeeeecccctttt, it will timeout prematurely. Internally, eeeexxxxppppeeeecccctttt calls read() which can be interrupted by signals. If you define signal handlers, you can choose to restart or abort eeeexxxxppppeeeecccctttt's internal read. The variable, eeeexxxxpppp____rrrreeeeaaaaddddiiiinnnngggg, is true iff eeeexxxxppppeeeecccctttt's read has been interrupted. longjmp(exp_readenv,EXP_ABORT) will abort the read. longjmp(exp_readenv,EXP_RESTART) will restart the read. LLLLOOOOGGGGGGGGIIIINNNNGGGG eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____lllloooogggguuuusssseeeerrrr;;;; eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____llllooooggggffffiiiilllleeee____aaaallllllll eeeexxxxtttteeeerrrrnnnn FFFFIIIILLLLEEEE ****eeeexxxxpppp____llllooooggggffffiiiilllleeee;;;; If eeeexxxxpppp____lllloooogggguuuusssseeeerrrr is nonzero, eeeexxxxppppeeeecccctttt sends any output from the spawned process to stdout. Since interactive programs typically echo their input, this usually suffices to show both sides of the conversation. If eeeexxxxpppp____llllooooggggffffiiiilllleeee is also nonzero, this same output is written to the stream defined by eeeexxxxpppp____llllooooggggffffiiiilllleeee. If eeeexxxxpppp____llllooooggggffffiiiilllleeee____aaaallllllll is non-zero, eeeexxxxpppp____llllooooggggffffiiiilllleeee is written regardless of the value of eeeexxxxpppp____lllloooogggguuuusssseeeerrrr. Page 9 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) DDDDEEEEBBBBUUUUGGGGGGGGIIIINNNNGGGG While I consider the library to be easy to use, I think that the standalone expect program is much, much, easier to use than working with the C compiler and its usual edit, compile, debug cycle. Unlike typical C programs, most of the debugging isn't getting the C compiler to accept your programs - rather, it is getting the dialogue correct. Also, translating scripts from expect to C is usually not necessary. For example, the speed of interactive dialogues is virtually never an issue. So please try the standalone 'expect' program first. I suspect it is a more appropriate solution for most people than the library. Nonetheless, if you feel compelled to debug in C, here are some tools to help you. eeeexxxxtttteeeerrrrnnnn iiiinnnntttt eeeexxxxpppp____iiiissss____ddddeeeebbbbuuuuggggggggiiiinnnngggg;;;; eeeexxxxtttteeeerrrrnnnn FFFFIIIILLLLEEEE ****eeeexxxxpppp____ddddeeeebbbbuuuuggggffffiiiilllleeee;;;; While expect dialogues seem very intuitive, trying to codify them in a program can reveal many surprises in a program's interface. Therefore a variety of debugging aids are available. They are controlled by the above variables, all 0 by default. Debugging information internal to eeeexxxxppppeeeecccctttt is sent to stderr when eeeexxxxpppp____iiiissss____ddddeeeebbbbuuuuggggggggiiiinnnngggg is non-zero. The debugging information includes every character received, and every attempt made to match the current input against the patterns. In addition, non-printable characters are translated to a printable form. For example, a control-C appears as a caret followed by a C. If eeeexxxxpppp____llllooooggggffffiiiilllleeee is non- zero, this information is also written to that stream. If eeeexxxxpppp____ddddeeeebbbbuuuuggggffffiiiilllleeee is non-zero, all normal and debugging information is written to that stream, regardless of the value of eeeexxxxpppp____iiiissss____ddddeeeebbbbuuuuggggggggiiiinnnngggg. CCCCAAAAVVVVEEEEAAAATTTTSSSS The stream versions of the eeeexxxxppppeeeecccctttt functions are much slower than the file descriptor versions because there is no way to portably read an unknown number of bytes without the potential of timing out. Thus, characters are read one at a time. You are therefore strongly encouraged to use the file descriptor versions of eeeexxxxppppeeeecccctttt (although, automated versions of interactive programs don't usually demand high speed anyway). You can actually get the best of both worlds, writing with the usual stream functions and reading with the file descriptor versions of eeeexxxxppppeeeecccctttt as long as you don't attempt to intermix other stream input functions (e.g., fgetc). To Page 10 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) do this, pass fileno(stream) as the file descriptor each time. Fortunately, there is little reason to use anything but the eeeexxxxppppeeeecccctttt functions when reading from interactive programs. There is no matching exp_pclose to exp_popen (unlike popen and pclose). It only takes two functions to close down a connection (fclose() followed by waiting on the pid), but it is not uncommon to separate these two actions by large time intervals, so the function seems of little value. If you are running on a Cray running Unicos (all I know for sure from experience), you must run your compiled program as root or setuid. The problem is that the Cray only allows root processes to open ptys. You should observe as much precautions as possible: If you don't need permissions, setuid(0) only immediately before calling one of the spawn functions and immediately set it back afterwards. Normally, ssssppppaaaawwwwnnnn takes little time to execute. If you notice spawn taking a significant amount of time, it is probably encountering ptys that are wedged. A number of tests are run on ptys to avoid entanglements with errant processes. (These take 10 seconds per wedged pty.) Running expect with the -d option will show if eeeexxxxppppeeeecccctttt is encountering many ptys in odd states. If you cannot kill the processes to which these ptys are attached, your only recourse may be to reboot. BBBBUUUUGGGGSSSS The eeeexxxxpppp____ffffeeeexxxxppppeeeecccctttt functions don't work at all under HP-UX - it appears to be a bug in getc. Follow the advice (above) about using the eeeexxxxpppp____eeeexxxxppppeeeecccctttt functions (which doesn't need to call getc). If you fix the problem (before I do - please check the latest release) let me know. SSSSEEEEEEEE AAAALLLLSSSSOOOO An alternative to this library is the eeeexxxxppppeeeecccctttt program. eeeexxxxppppeeeecccctttt interprets scripts written in a high-level language which direct the dialogue. In addition, the user can take control and interact directly when desired. If it is not absolutely necessary to write your own C program, it is much easier to use eeeexxxxppppeeeecccctttt to perform the entire interaction. It is described further in the following references: "_e_x_p_e_c_t: _C_u_r_i_n_g _T_h_o_s_e _U_n_c_o_n_t_r_o_l_l_a_b_l_e _F_i_t_s _o_f _I_n_t_e_r_a_c_t_i_v_i_t_y" by Don Libes, Proceedings of the Summer 1990 USENIX Conference, Anaheim, California, June 11-15, 1990. "_U_s_i_n_g _e_x_p_e_c_t _t_o _A_u_t_o_m_a_t_e _S_y_s_t_e_m _A_d_m_i_n_i_s_t_r_a_t_i_o_n _T_a_s_k_s" by Don Libes, Proceedings of the 1990 USENIX Large Installation Systems Administration Conference, Colorado Springs, Page 11 (printed 7/23/95) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) UUUUNNNNIIIIXXXX SSSSyyyysssstttteeeemmmm VVVV ((((11112222 DDDDeeeecccceeeemmmmbbbbeeeerrrr 1111999999991111)))) LLLLIIIIBBBBEEEEXXXXPPPPEEEECCCCTTTT((((3333)))) Colorado, October 17-19, 1990. expect(1), alarm(3), read(2), write(2), fdopen(3), execve(2), execvp(3), longjmp(3), pty(4). There are several examples C programs in the test directory of eeeexxxxppppeeeecccctttt's source distribution which use the expect library. AAAAUUUUTTTTHHHHOOOORRRR Don Libes, libes@nist.gov, National Institute of Standards and Technology AAAACCCCKKKKNNNNOOOOWWWWLLLLEEEEDDDDGGGGEEEEMMMMEEEENNNNTTTTSSSS Thanks to John Ousterhout (UCBerkeley) for supplying the pattern matcher. Design and implementation of the eeeexxxxppppeeeecccctttt library was paid for by the U.S. government and is therefore in the public domain. However the author and NIST would like credit if this program and documentation or portions of them are used. Page 12 (printed 7/23/95)